#ifndef TASK_H
#define TASK_H

#include "types.h"
#include "cpu.h"
#include "list.h"
#include "file.h"

#define TASK_NAME_SIZE 32
#define TASK_TIME_SLICE_DEFAULT 10
#define TASK_OFILE_NR           128

#define IDLE_TASK_STACK_SIZE 1024

#define TASK_FLAGS_SYSTEM (1<<0)

typedef struct _task_t{
    //uint32_t * stack; //task stack pointer,the second method of task switch
    enum{
        TASK_CREATED,
        TASK_RUNNING,
        TASK_SLEEP,
        TASK_READY,
        TASK_WAITING,
        TASK_ZOMBIE,
    }state;

    int pid;
    struct _task_t * parent;
    uint32_t heap_start;
    uint32_t heap_end;

    int sleep_ticks;//sleep counter,dec
    int time_ticks;//time counter
    int slice_ticks;//time slice can run,dec

    int status;//return status

    file_t * file_table[TASK_OFILE_NR];
    char name[TASK_NAME_SIZE];

    list_node_t run_node;  //ready list node
    list_node_t wait_node;
    list_node_t all_node; //all tasks list node
    tss_t tss;
    int tss_selector;

}task_t;

int task_init(task_t *task, const char * name,int flag,uint32_t entry,uint32_t esp);//flag 1 system, 0 user
void task_switch_from_to(task_t *from,task_t * to);

typedef struct _task_manager_t{
    list_t task_list; //the list of all tasks
    list_t ready_list;
    list_t sleep_list;

    task_t *current_task;
    task_t first_task;
    task_t idle_task;

    int app_code_sel;
    int app_data_sel;
}task_manager_t;
void task_manager_init(void);
void task_first_init(void);
task_t * task_current_task(void);
task_t * task_first_task(void);

void task_set_ready(task_t *task);
void task_set_block(task_t *task);

int sys_yield(void);
void task_dispatch(void);
void task_time_tick(void);

void task_set_sleep(task_t *task,uint32_t ticks);
void task_set_wakeup(task_t *task);
void task_start(task_t * task);

void sys_sleep(uint32_t ms);
int sys_getpid(void);
int sys_fork(void);
int sys_execve(char *name,char **argv,char **env);
void sys_exit(int status);
int sys_wait(int * status);

int task_alloc_fd(file_t * file);
void task_release_fd(int fd);
file_t * task_file(int fd);

typedef struct _task_args_t{
    uint32_t ret_addr; //return address,not used in code
    uint32_t argc;
    char **argv;
    char **env;
}task_args_t;
#endif